import {CardRank, CardSuit, MapCardConfig, OrderCardStatus} from '../GameDef';

export interface ICard {
    getName(): string;
    reset(): void;
    clone(): this;
    valueEquals(other: BaseCard): boolean;
    equals(other: BaseCard): boolean;
}


export class BaseCard implements ICard {
    private _uid: number;
    private _suit: CardSuit;
    private _rank: CardRank;
    private _orderId: number = 0;
    private _x: number = 0;
    private _y: number = 0;
    private _rotation: number = 0;

    get uid(): number {
        return this._uid;
    }

    get suit(): CardSuit {
        return this._suit;
    }

    get rank(): CardRank {
        return this._rank;
    }

    get x(): number {
        return this._x;
    }

    set x(value: number) {
        this._x = value;
    }

    get y(): number {
        return this._y;
    }

    set y(value: number) {
        this._y = value;  
    }

    get rotation(): number {
     
        return this._rotation;
    }
    set rotation(value: number) {
        this._rotation = value;
    }

    constructor(uid: number, cardId: number, orderId: number) {
        this._uid = uid;
        this.setValue(cardId);
        this._orderId = orderId;
    }

    clone(): this {
        return Object.assign(Object.create(Object.getPrototypeOf(this)), this);
    }

    setValue(cardId: number) {
        this._suit = Math.floor(cardId / 13) as CardSuit;
        this._rank = (cardId % 13) as CardRank;
    }

    setUid(uid: number) {
        this._uid = uid; 
    }

    getName(): string {
        const suitNames = ['黑桃', '红桃', '梅花', '方块'];
        const rankNames = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
        return `${suitNames[this._suit]}${rankNames[this._rank]}`;
    }

    get cardId(): number {
        return this._suit * 13 + this._rank;
    }

    set orderId(orderId: number) {
        this._orderId = orderId;
    }

    get orderId(): number {
        return this._orderId;
    }

    equals(other: BaseCard): boolean {
        return this.uid === other.uid;
    }

    valueEquals(other: BaseCard): boolean {
        return this._suit === other._suit && this._rank === other._rank;
    }

    reset(): void {
        this._uid = 0;
        this._suit = CardSuit.SPADE;
        this._rank = CardRank.ACE;
        this._orderId = 0;

    }

    fixWrongCard(value: number, orderId: number): number {
        this.setValue(value);
        this.orderId = orderId;
        return this.uid;
    }
}

export class CardInPool extends BaseCard {

    private _isUsed: boolean = false;
    constructor(uid: number, cardId: number, orderId: number) {
        super(uid, cardId, orderId);
    }

    get isUsed(): boolean {
        return this._isUsed;
    }

    markAsUsed(): void {
        this._isUsed = true;
    }
    reset(): void {
        super.reset();
        this._isUsed = false;
    }
}

export class CardInMountain extends BaseCard {
    public layerid: number = -1;
    public index: number = -1;
    public isOpen = false;
    constructor(card: CardInPool, mapCardCfg: MapCardConfig) {
        super(card.uid, card.cardId, card.orderId);
        this.updateTranform(mapCardCfg.x, mapCardCfg.y, mapCardCfg.rotation);
        this.updateLevel(mapCardCfg.layerid, mapCardCfg.index);
    }

    updateTranform(x: number, y: number, rotation: number) {
        this.x = x;
        this.y = y;
        this.rotation = rotation;
    }

    updateLevel(layerid: number, index: number) {
        this.layerid = layerid;
        this.index = index;
    }

    static swapUidAndValue(ca: CardInMountain, cb: CardInMountain) {
        // 保存位置相关属性
        const uid = ca.uid;
        const ccid = ca.cardId;
        
        ca.setUid(cb.uid );
        ca.setValue(cb.cardId);

        cb.setUid(uid);
        cb.setValue(ccid);
    }
}

export class CardInOrder extends BaseCard {
    status: OrderCardStatus;
    checkSuit: boolean;

    constructor(uid: number, cardId: number, orderId: number, suit: boolean, status: OrderCardStatus = OrderCardStatus.NONE) {
        super(uid, cardId, orderId);
        this.checkSuit = suit;
        this.status = status;
    }

    isFit(card: BaseCard, checkSuit:boolean = this.checkSuit): boolean {
        if (this.status != OrderCardStatus.WAIT) {
            return false;
        }

        if (checkSuit) {
            return this.suit == card.suit && this.rank == card.rank;
        } else {
            return this.rank == card.rank;
        }
    }
}